﻿#include "BackWgt.h"
#include <QPainter>
#include <QPainterPath>
#include <QTime>
#include <QDebug>
#include <QtMath>
#include <QPointF>
#include <QFile>
#include <QLinearGradient>
#include <QBitmap>

BackWgt::BackWgt(QWidget *parent) :
    QWidget(parent)
{
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
    timer->start(16);
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
    //设置颜色
    this->setColor();
    //设置位置
    this->setPoint();
    /**
     * 当前高亮位置，x，y
     * @type {Array<number>} 高亮位置x,y
    */
    double randomNum = rand()%100/(double)101;
    nowHiLightSpeed[0] = randomNum * 0.06 - 0.03;
    nowHiLightSpeed[1] = randomNum * 0.1 - 0.05;
    nowHiLight[0] = randomNum + 1;
    nowHiLight[1] = randomNum + 5;
}

BackWgt::~BackWgt()
{
}

static qint64 timestamp = QDateTime::currentDateTime().toMSecsSinceEpoch();

void BackWgt::paintEvent(QPaintEvent *e)
{
    QPainter p(this);

    qint64 interval = QDateTime::currentDateTime().toMSecsSinceEpoch() - timestamp;
    timestamp = QDateTime::currentDateTime().toTime_t();
    double randomNum = rand()%100/(double)101;
    //计算最新的高亮移动速度
    nowHiLightSpeed[0] += (randomNum - 0.5) * 0.028;
    nowHiLightSpeed[1] += (randomNum - 0.5) * 0.04;

    //限制最大速度
    if (nowHiLightSpeed[0] > 0.3) nowHiLightSpeed[0] = 0.3;
    if (nowHiLightSpeed[0] < -0.3) nowHiLightSpeed[0] = -0.3;
    if (nowHiLightSpeed[1] > 0.6) nowHiLightSpeed[1] = 0.6;
    if (nowHiLightSpeed[1] < -0.6) nowHiLightSpeed[1] = -0.6;

    //移动点
    nowHiLight[0] += nowHiLightSpeed[0];
    nowHiLight[1] += nowHiLightSpeed[1];

    if (nowHiLight[0] < 0) {
        nowHiLight[0] = 0;
        nowHiLightSpeed[0] = randomNum * 0.014;
    }
    if (nowHiLight[0] >= 3) {
        nowHiLight[0] = 2.999;
        nowHiLightSpeed[0] = randomNum * -0.014;
    }
    if (nowHiLight[1] < 0) {
        nowHiLight[1] = 0;
        nowHiLightSpeed[1] = randomNum * 0.02;
    }
    if (nowHiLight[1] >= 11) {
        nowHiLight[1] = 10.999;
        nowHiLightSpeed[1] = randomNum * -0.02;
    }
    setBright(nowHiLight[0], nowHiLight[1], 0.5, 1);

    //重算坐标位置
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 12; j++) {
            pointsNow[i][j] = getMovePoint(points[i][j], pointsMoveTime[i][j], interval, pointsTarget[i][j]);
        }
    }

    //绘制前最后的准备
    for (int j = 0; j < 11; j++) {
        for (int i = 0; i < 3; i++) {
            //设置颜色
            shapeColorUP[i][j] = getMoveColor(shapeColorUPFrom[i][j], shapeColorUPTarget[i][j], shapeColorUPTime[i][j], interval, shapeBright[i][j]);
            shapeColorDOWN[i][j] = getMoveColor(shapeColorDOWNFrom[i][j], shapeColorDOWNTarget[i][j], shapeColorDOWNTime[i][j], interval, shapeBright[i][j]);
            //绘制图像
            drawTriangle(&p,pointsNow[i][j], pointsNow[i][j + 1], pointsNow[i + 1][j], shapeColorUP[i][j]);
            drawTriangle(&p,pointsNow[i][j + 1], pointsNow[i + 1][j], pointsNow[i + 1][j + 1], shapeColorDOWN[i][j]);
        }
    }
    p.setPen(Qt::NoPen);
    // 线性渐变
    QLinearGradient linearGradient(QPointF(0, 180),QPointF(0, 50));
    // 插入颜色
    linearGradient.setColorAt(0, QColor(240,240,240,255));
    //linearGradient.setColorAt(0.5, Qt::red);
    linearGradient.setColorAt(1, QColor(240,240,240,0));
    // 指定渐变区域以外的区域的扩散方式
    //linearGradient.setSpread(QGradient::RepeatSpread);
    // 使用渐变作为画刷
    p.setBrush(linearGradient);
    p.drawRect(this->rect());

    p.setBrush(QColor("#a0c8dc"));
    p.drawRect(QRect(0,280,450,50));
}

//画三角形
void BackWgt::drawTriangle(QPainter* p,QPointF a, QPointF b, QPointF c, QColor color)
{
    //p->save();
    QPainterPath path;
    path.moveTo(a);
    path.lineTo(b);
    path.lineTo(c);
    p->setPen(color);
    p->setBrush(color);
    p->drawPath(path);
    //p->restore();
}

//缓动曲线
//x(percentComplete) ∈ [0,1]， 并按照 x ∈ [0,0.5) 或 x ∈ [0.5,1] 返回对应 f(x) 的值，组成一个连贯图像
double BackWgt::makeEaseInOut2(double percentComplete)
{
    if (percentComplete < 0.5) {
            percentComplete *= 2;
            return qPow(percentComplete, 2) / 2;
        } else {
            percentComplete = 1 - percentComplete;
            percentComplete *= 2;
            return 1 - qPow(percentComplete, 2) / 2;
        }
}

//设置颜色
void BackWgt::setColor()
{
    //设置颜色
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 11; j++) {
            shapeColorUPFrom[i][j] = getRandomRGB();
            shapeColorDOWNFrom[i][j] = getRandomRGB();
            shapeColorUPTarget[i][j] = getRandomRGBLight();
            shapeColorDOWNTarget[i][j] = getRandomRGBLight();
            shapeColorUPTime[i][j] = 1000 + rand()%2000;
            shapeColorDOWNTime[i][j] = 1000 + rand()%2000;
        }
    }
}

//设置点坐标,可通过更改x,y的系数控制绘制区域
void BackWgt::setPoint()
{
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 12; j++) {
            int x =  j * 90 - 300 + rand()%50;
            int y = i * 80 - 40 + rand()%10;
            points[i][j] = QPoint(x,y);
            x = x+rand()%260;
            y = y+rand()%20;
            pointsTarget[i][j] = QPointF(x,y);
            pointsMoveTime[i][j] = 5000 + rand()%3000;
        }
    }
}

/**
 * @description 按照一种缓动方式，得到某点在t毫秒时的x，y，返回一个数组[x,y]
 * @param {Array<number>} point 要移动的点
 * @param {number} t 单程移动所需时间（ms）pointsMoveTime
 * @param {number} g 已经经过的时间
 * @param {number} target 要移动到的目标点
*/
QPointF BackWgt::getMovePoint(QPointF start, int t, qint64 g, QPointF target) {
    QPointF toMove = target - start;
    double persent = g / (double)t;

    int nTemp = static_cast<int>(persent);
    int nResult = nTemp % 2;
    persent = persent - nTemp + nResult;

    double persentRe;

    if (persent < 1) {
        persentRe = makeEaseInOut2(persent);
    } else {
        persentRe = 1 - makeEaseInOut2(persent - 1);
    }
    double x = start.x() + persentRe*toMove.x();
    double y = start.y() + persentRe*toMove.y();
    return QPointF(x,y);
}

/**
 * @description 按照等速渐变，得到某点在t毫秒时的颜色，返回一个字符串
 * @param {Array<number>} from 来源颜色
 * @param {number} t 单程移动所需时间（ms）
 * @param {number} g 已经经过的时间
 * @param {number} l 额外亮度增益，最大1，默认0
 * @param {Array<number>} to 目标颜色
*/
QColor BackWgt::getMoveColor(QColor from, QColor to, int t, qint64 gone, double l) {
    double persent = gone / (double)t;

    int nTemp = static_cast<int>(persent);
    int nResult = nTemp % 2;
    persent = persent - nTemp + nResult;

    if (persent > 1) persent = 2 - persent;

    qreal r = from.red() + (to.red() - from.red()) * persent;
    qreal g = from.green() + (to.green() - from.green()) * persent;
    qreal b = from.blue() + (to.blue() - from.blue()) * persent;

    //如果存在亮度
    if (l > 0) {
        qreal bAdded;
        bAdded = (255 - b) * l;
        if (b > 0.00000001 || b < -0.00000001) {
            b = (255 - b) * l + b;
        }
        if (g > 0.00000001 || g < -0.00000001) {
            g += bAdded;
            if (g > 255) g = 255;
        }
    }
    r = static_cast<int>(r);
    g = static_cast<int>(g);
    b = static_cast<int>(b);
    return QColor(r,g,b);

}

/**
 * @description 随机得到一个亮一些的rgb颜色数组
*/
QColor BackWgt::getRandomRGBLight() {
    double randomNum = rand()%100/(double)101;
    randomNum = randomNum / 2 + 0.5;
    int g = 140 + static_cast<int>(randomNum * 45);
    int b = 180 + static_cast<int>(randomNum * 55);
    return QColor(0,g,b);
}

//获取一个随机的颜色
QColor BackWgt::getRandomRGB()
{
    double randomNum = rand()%100/(double)101;
    int g = 130 + static_cast<int>(randomNum * 30);
    int b = 160 + static_cast<int>(randomNum * 50);
    return QColor(0,g,b);
}

/**
 * @description 设置图形亮度
 * @param {Array<Array<number>>} brightArr 要用于存放亮度的已经被清空的数组
 * @param {number} pointX 目标坐标X
 * @param {number} pointY 目标坐标Y
 * @param {number} decaySpeed 每一格光照强度等量衰减
 * @param {number} bright 目标所在的光照强度
*/
void BackWgt::setBright(double pointX, double pointY,double decaySpeed,int bright) {
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 11; j++) {
            shapeBright[i][j] = bright - decaySpeed * qSqrt((pointX - i) * (pointX - i) + (pointY - j) * (pointY - j)) * 0.7;
            if (shapeBright[i][j] < 0) shapeBright[i][j] = 0;
        }
    }
}
